package com.access.boot.autoconfigure.apisdk.proxy.aop;

import com.access.boot.autoconfigure.apisdk.aop.Advice;
import com.access.boot.autoconfigure.apisdk.aop.AdvisedSupport;
import com.access.boot.autoconfigure.apisdk.aop.Advisor;
import com.access.boot.autoconfigure.apisdk.aop.AdvisorChainFactory;
import com.access.boot.autoconfigure.apisdk.aop.DefaultPointcutAdvisor;
import com.access.boot.autoconfigure.apisdk.aop.MethodMatcher;
import com.access.boot.autoconfigure.apisdk.aop.Pointcut;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author Yangzhen
 * @date 2022/6/2 16:35
 * @since 1.0.0
 */
public class ApiSdkAdvisedSupport extends AdvisedSupport {

    private Object target;

    private EnhanceProxyInstance enhanceProxyInstance;

    private List<Class<?>> interfaces = new ArrayList<>();

    AdvisorChainFactory advisorChainFactory = new AdvisorChainFactory();

    private List<Advisor> advisors = new ArrayList<>();

    public void addAdvisors(Collection<Advisor> advisors) {
        if (!CollectionUtils.isEmpty(advisors)) {
            for (Advisor advisor : advisors) {
                this.advisors.add(advisor);
            }
        }
    }

    public List<Advisor> getAdvisors() {
        return advisors;
    }

    public List<Object> getInterceptors(Method method, Class<?> targetClass) {
        return advisorChainFactory.getInterceptors(this, method, targetClass);
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public void setInterfaces(Class<?>... interfaces) {
        for (Class<?> ifc : interfaces) {
            this.interfaces.add(ifc);
        }
    }

    public void addAdvice(Advice advice) {
        this.advisors.add(new DefaultPointcutAdvisor(new Pointcut() {
            @Override
            public MethodMatcher getMethodMatcher() {
                return new MethodMatcher() {
                    @Override
                    public boolean matches(Method method) {
                        return true;
                    }
                };
            }
        }, advice));
    }

    public Class<?>[] getProxiedInterfaces() {
        return ClassUtils.toClassArray(this.interfaces);
    }

    public void setEnhanceProxyInstance(EnhanceProxyInstance enhanceProxyInstance) {
        this.enhanceProxyInstance = enhanceProxyInstance;
    }

    public EnhanceProxyInstance getEnhanceProxyInstance() {
        return enhanceProxyInstance;
    }
}
